package com.bestcem.xm.member.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.sql.ConditionConstant;
import com.bestcem.xm.common.core.uitls.JsonUtil;
import com.bestcem.xm.component.security.annotation.AuthIgnore;
import com.bestcem.xm.label.dao.LabelValueDao;
import com.bestcem.xm.label.entity.pojo.LabelValueDO;
import com.bestcem.xm.member.controller.param.HttpQueryBaseFieldParam;
import com.bestcem.xm.member.entity.pojo.FootprintDO;
import com.bestcem.xm.member.entity.pojo.MemberQueryFieldDO;
import com.bestcem.xm.member.enums.MemberTypeEnum;
import com.bestcem.xm.member.grpc.client.XmQdesClient;
import com.bestcem.xm.member.grpc.client.dto.QdesProjectDTO;
import com.bestcem.xm.member.service.FootprintService;
import com.bestcem.xm.member.service.MemberQueryFieldService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@RestController("memberScriptController")
@RequestMapping("/member/script")
public class ScriptController {

    @Resource
    private MemberQueryFieldService memberQueryFieldService;

    @Resource
    private FootprintService footprintService;

    /**
     * 问卷服务客户端
     */
    @Autowired
    private XmQdesClient qdesClient;

    @Autowired
    LabelValueDao labelValueDao;


    @AuthIgnore
    @PutMapping("/member_query_field/update")
    public String updateMemberQueryField() {
        // 修改 MemberQueryField 历史数据
        int batchSize = 1000;
        int offset = 0;
        while (true) {
            List<MemberQueryFieldDO> memberQueryFields = memberQueryFieldService.findAll(offset, batchSize);
            if (CollectionUtils.isEmpty(memberQueryFields)) {
                break;
            }
            for (MemberQueryFieldDO memberQueryField : memberQueryFields) {
                String baseFields1 = memberQueryField.getBaseFields();
                List<HttpQueryBaseFieldParam> param =
                        JSONObject.parseArray(baseFields1, HttpQueryBaseFieldParam.class);
                List<HttpQueryBaseFieldParam> httpQueryBaseFieldParams =
                        param.stream().filter(item -> item.getField().equals("nickname")).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(httpQueryBaseFieldParams)) {
                    continue;
                }
                if (MemberTypeEnum.INDIVIDUAL.getIndex() == memberQueryField.getMemberType()) {
                    HttpQueryBaseFieldParam param1 = new HttpQueryBaseFieldParam();
                    param1.setDisplayName("微信昵称");
                    param1.setField("nickname");
                    param1.setShow(false);
                    param.add(3, param1);
                    memberQueryFieldService.updateBaseQueryField(memberQueryField.getId(), JSONObject.toJSONString(param));
                }
            }

            offset += batchSize;
        }

        batchSize = 1000;
        offset = 0;
        while (true) {
            List<MemberQueryFieldDO> memberQueryFields = memberQueryFieldService.findAll(offset, batchSize);
            if (CollectionUtils.isEmpty(memberQueryFields)) {
                break;
            }
            for (MemberQueryFieldDO memberQueryField : memberQueryFields) {
                String baseFields1 = memberQueryField.getBaseFields();
                List<HttpQueryBaseFieldParam> param =
                        JSONObject.parseArray(baseFields1, HttpQueryBaseFieldParam.class);
                List<HttpQueryBaseFieldParam> httpQueryBaseFieldParams =
                        param.stream().filter(item -> item.getField().equals("union_id")).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(httpQueryBaseFieldParams)) {
                    continue;
                }
                if (MemberTypeEnum.INDIVIDUAL.getIndex() == memberQueryField.getMemberType()) {
                    HttpQueryBaseFieldParam param1 = new HttpQueryBaseFieldParam();
                    param1.setDisplayName("微信UnionID");
                    param1.setField("union_id");
                    param1.setShow(false);
                    param.add(12, param1);
                    memberQueryFieldService.updateBaseQueryField(memberQueryField.getId(), JSONObject.toJSONString(param));
                }
            }

            offset += batchSize;
        }
        return "success";
    }

    @AuthIgnore
    @GetMapping(value = "/footprint/update")
    public String updateFootprint() {
        // 获取 所有 demo 的且为答卷的足迹点
        List<FootprintDO> footprintDOS = footprintService.listFootprintsByIsCopy();
        if (CollUtil.isNotEmpty(footprintDOS)) {
            log.error("需要修复的足迹点有 {}个",  footprintDOS.size());
            for (int i = 0; i < footprintDOS.size(); i++) {
                FootprintDO item = footprintDOS.get(i);
                String content = item.getContent();
                try {
                    if (StrUtil.isNotBlank(content)) {
                        // 转换成json
                        JSONObject contentJson = JSONObject.parseObject(content);
                        if (ObjectUtil.isNotEmpty(contentJson)) {
                            if (contentJson.containsKey("project_id")) {
                                // 获取projectId
                                String projectId = contentJson.getString("project_id");
                                // 更新 projectId
                                String newProjectId = getNewProjectId(projectId, item.getOrgId());
                                if (StrUtil.isNotEmpty(newProjectId)) {
                                    // 替换原有的projectId
                                    contentJson.put("project_id", newProjectId);
                                    String contentStr = JSONObject.toJSONString(contentJson);
                                    item.setContent(contentStr);
                                    footprintService.updateContent(item);
                                    log.error("足迹点 {} 更新 {}->{}",  item.getId(), projectId, newProjectId);
                                }
                            }
                        }
                    }
                } catch ( Exception e) {
                    log.error("足迹点修复失败 {}", item.getId(), e);
                }
                log.error("足迹点修复 {}/{}" ,(i+1), footprintDOS.size());
            }
        }
        return "success";
    }


    private String getNewProjectId(String projectId, String orgId) {
        // 获取改projectId 的
        ServiceResult<QdesProjectDTO> projectServiceResult = qdesClient.getProject(projectId);
        if (!projectServiceResult.isSuccess()) {
            log.error("【足迹点修复】获取项目信息失败 {}", projectServiceResult.getMsg());
            return null;
        }
        QdesProjectDTO data = projectServiceResult.getData();
        String companyId = data.getCompanyId();
        if (orgId.equals(companyId)) {
            log.error("【足迹点修复】数据正常 不进行修复 {} {}", companyId, orgId);
            return null;
        }

        String code = data.getCode();
        // 根据新环境orgId和code获取新的projectId
        ServiceResult<List<QdesProjectDTO>> listServiceResult = qdesClient.listProject(orgId, code);
        if (!listServiceResult.isSuccess()) {
            log.error("【足迹点修复】获取新的projectId失败 {}", projectServiceResult.getMsg());
            return null;
        }
        List<QdesProjectDTO> list = listServiceResult.getData();
        if (list.size() != 1) {
            log.error("【足迹点修复】listProject 结果数量应为1, 实际为:{}", list.size());
            return null;
        }
        QdesProjectDTO newProjectDTO = list.get(0);
        String newProjectId = newProjectDTO.getId();
        return newProjectId;

    }

    @AuthIgnore
    @PostMapping("/member_label_value/recovery")
    public String recoverMemberLabelValue() {
        int limit = 1000;
        long offset = 0;
        // project 旧新 id map
        Map<String, String> projectIdMap = new HashMap<>();
        // 获取project 旧新 id map
        setProjectIdMap(limit, offset, projectIdMap);
        // 恢复数据
        recover(limit, offset, projectIdMap);
        return "success";
    }

    private void recover(int limit, long offset, Map<String, String> projectIdMap) {
        while (true) {
            log.error("【联系人】临时进度日志 recover, offset:{} limit:{}", offset, limit);
            List<LabelValueDO> labelValues = labelValueDao.listBySamplePaging(offset, limit);
            if (CollectionUtils.isEmpty(labelValues)) {
                break;
            }
            for (LabelValueDO labelValue : labelValues) {
                String recoveredCondition = replaceConditionProjectId(labelValue.getCondition(), projectIdMap);
                labelValue.setCondition(recoveredCondition);
                labelValueDao.updateCondition(labelValue);
            }
            offset += limit;
        }
    }

    private void setProjectIdMap(int limit, long offset, Map<String, String> projectIdMap) {
        while (true) {
            log.error("【联系人】临时进度日志 setProjectIdMap, offset:{} limit:{}", offset, limit);
            List<LabelValueDO> labelValues = labelValueDao.listBySamplePaging(offset, limit);
            if (CollectionUtils.isEmpty(labelValues)) {
                break;
            }
            // 首先获取全部的旧新id map,因为可能会有重复的数据,减少grpc交互
            for (LabelValueDO labelValueDO : labelValues) {
                String condition = labelValueDO.getCondition();
                if (!StringUtils.hasText(condition)){
                    continue;
                }
                String orgId = labelValueDO.getOrgId();
                JSONObject conditionObj = JsonUtil.tryConvertToJSONObject(condition);
                List<JSONObject> filters = (List<JSONObject>) conditionObj.get(ConditionConstant.FILTERS);
                if (CollUtil.isNotEmpty(filters)) {
                    for (JSONObject filter : filters) {
                        if (!filter.containsKey(ConditionConstant.PROJECT_ID)) {
                            continue;
                        }
                        String projectId = filter.getString(ConditionConstant.PROJECT_ID);
                        if (projectIdMap.containsKey(projectId)) {
                            continue;
                        }
                        // 根据projectId 获取 编号code
                        ServiceResult<QdesProjectDTO> projectServiceResult = qdesClient.getProject(projectId);
                        if (!projectServiceResult.isSuccess()) {
                            log.error("【联系人】获取项目信息失败 {}", projectServiceResult.getMsg());
                            continue;
                        }
                        QdesProjectDTO projectDTO = projectServiceResult.getData();
                        String code = projectDTO.getCode();
                        // 根据新环境orgId和code获取新的projectId
                        ServiceResult<List<QdesProjectDTO>> listServiceResult = qdesClient.listProject(orgId, code);
                        if (!listServiceResult.isSuccess()) {
                            log.error("【联系人】获取新的projectId失败, 新orgId:{}, code{}, msg:{}", orgId, code, projectServiceResult.getMsg());
                            continue;
                        }
                        List<QdesProjectDTO> list = listServiceResult.getData();
                        if (list.size() != 1) {
                            log.error("【联系人】listProject 结果数量应为1, 实际为:{}", list.size());
                            continue;
                        }
                        QdesProjectDTO newProjectDTO = list.get(0);
                        String newProjectId = newProjectDTO.getId();
                        projectIdMap.put(projectId, newProjectId);
                    }
                }
                if (conditionObj.containsKey(ConditionConstant.PROJECT_ID)) {
                    String projectId = conditionObj.getString(ConditionConstant.PROJECT_ID);
                    // 根据projectId 获取 编号code
                    ServiceResult<QdesProjectDTO> projectServiceResult = qdesClient.getProject(projectId);
                    if (!projectServiceResult.isSuccess()) {
                        log.error("【联系人】获取项目信息失败 {}", projectServiceResult.getMsg());
                        continue;
                    }
                    QdesProjectDTO projectDTO = projectServiceResult.getData();
                    String code = projectDTO.getCode();
                    // 根据新环境orgId和code获取新的projectId
                    ServiceResult<List<QdesProjectDTO>> listServiceResult = qdesClient.listProject(orgId, code);
                    if (!listServiceResult.isSuccess()) {
                        log.error("【联系人】获取新的projectId失败, 新orgId:{}, code{}, msg:{}", orgId, code, projectServiceResult.getMsg());
                        continue;
                    }
                    List<QdesProjectDTO> list = listServiceResult.getData();
                    if (list.size() != 1) {
                        log.error("【联系人】listProject 结果数量应为1, 实际为:{}", list.size());
                        continue;
                    }
                    QdesProjectDTO newProjectDTO = list.get(0);
                    String newProjectId = newProjectDTO.getId();
                    projectIdMap.put(projectId, newProjectId);
                }
            }
            offset += limit;
        }
    }


    private String replaceConditionProjectId(String condition, Map<String, String> projectIdMap) {
        if (StrUtil.isNotEmpty(condition)) {
            JSONObject conditionObj = JsonUtil.tryConvertToJSONObject(condition);
            List<JSONObject> filters = (List<JSONObject>) conditionObj.get(ConditionConstant.FILTERS);
            if (CollUtil.isNotEmpty(filters)) {
                filters.forEach(item -> {
                    if (item.containsKey(ConditionConstant.PROJECT_ID)) {
                        String projectId = item.getString(ConditionConstant.PROJECT_ID);
                        String newProjectId = projectIdMap.getOrDefault(projectId, "");
                        if (StrUtil.isNotEmpty(newProjectId)) {
                            item.put(ConditionConstant.PROJECT_ID, newProjectId);
                        } else {
                            log.error("【联系人】项目{}无法找到对应的新id, newProjectId:{}", projectId, newProjectId);
                        }
                    }
                });
                conditionObj.put(ConditionConstant.FILTERS, filters);
            }
            if (conditionObj.containsKey(ConditionConstant.PROJECT_ID)) {
                String projectId = conditionObj.getString(ConditionConstant.PROJECT_ID);
                String newProjectId = projectIdMap.getOrDefault(projectId, "");
                if (StrUtil.isNotEmpty(newProjectId)) {
                    conditionObj.put(ConditionConstant.PROJECT_ID, newProjectId);
                } else {
                    log.error("【联系人】项目{}无法找到对应的新id, newProjectId:{}", projectId, newProjectId);
                }
            }
            return JsonUtil.tryConvertToJSONString(conditionObj);
        }
        return condition;
    }

}
